package com.xiaoyu.base.view.list;

import android.content.Context;

import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;

import com.xiaoyu.base.event.EventWithRequestTag;
import com.xiaoyu.base.view.list.util.diff.BaseDiffAdapter;

import in.srain.cube.util.CLog;
import in.srain.cube.views.list.CubeRecyclerViewAdapter;
import in.srain.cube.views.list.PagedListDataModelWithRequestTag;

public class BaseListViewController<ListItemDataType, RequestTag> {

    private final static String TAG = "BaseListViewController";

    private final Context mContext;
    public Runnable mEmptyCallback;
    private Runnable mNotEmptyCallback;
    private RecyclerView mRecyclerView;
    private PagedListDataModelWithRequestTag<ListItemDataType, RequestTag> mListData;
    private RecyclerViewLoadMoreController mRecyclerViewLoadMoreController;
    private CubeRecyclerViewAdapter<ListItemDataType> mAdapter;
    private SwipeRefreshLayout mSwipeRefreshLayout;
    private boolean mDataHasLoaded = false;
    private boolean mShouldScrollToTopAtFirst = true;
    private boolean mShouldScrollToTop = true;
    private RecyclerView.AdapterDataObserver mAdapterDataObserver;

    public BaseListViewController(Context context, PagedListDataModelWithRequestTag<ListItemDataType, RequestTag> listData, CubeRecyclerViewAdapter<ListItemDataType> adapter, SwipeRefreshLayout swipeRefreshLayout, RecyclerView recyclerView) {
        mContext = context;
        mAdapter = adapter;
        mListData = listData;
        mSwipeRefreshLayout = swipeRefreshLayout;
        mRecyclerView = recyclerView;
        init();
    }

    public void tryToLoadFirstPageData() {
        CLog.d(TAG, "tryToLoadFirstPageData: %s", this);
        if (!mDataHasLoaded) {
            mListData.queryFirstPage();
            tryToShowLoadingForLoadFirstPageData();
        }
    }

    public void loadFirstPageData() {
        CLog.d(TAG, "loadFirstPageData: %s", this);
        mListData.queryFirstPage();
        tryToShowLoadingForLoadFirstPageData();
    }

    public void tryToRefreshFirstPageData(boolean shouldScrollToTop) {
        CLog.d(TAG, "tryToRefreshFirstPageData: %s", this);
        if (mDataHasLoaded) {
            mListData.queryFirstPage();
            mShouldScrollToTopAtFirst = shouldScrollToTop;
        }
    }

    private void tryToShowLoadingForLoadFirstPageData() {
        CLog.d(TAG, "tryToShowLoadingForLoadFirstPageData: %s", this);
        if (mSwipeRefreshLayout != null) {
            mSwipeRefreshLayout.postDelayed(() -> mSwipeRefreshLayout.setRefreshing(true), 1);
        }
    }

    private void tryToStopLoading() {
        CLog.d(TAG, "tryToStopLoading");
        if (mSwipeRefreshLayout != null) {
            mSwipeRefreshLayout.setRefreshing(false);
        }
    }

    public void setShouldScrollToTop(boolean shouldScrollToTop) {
        mShouldScrollToTop = shouldScrollToTop;
    }

    private void init() {
        if (mAdapter instanceof BaseDiffAdapter && mAdapterDataObserver == null) {
            mAdapterDataObserver = new RecyclerView.AdapterDataObserver() {
                @Override
                public void onItemRangeInserted(int positionStart, int itemCount) {
                    if (positionStart == 0 && (mShouldScrollToTopAtFirst || mShouldScrollToTop)) {
                        mRecyclerView.scrollToPosition(0);
                        mShouldScrollToTopAtFirst = false;
                    }
                }
            };
            mAdapter.registerAdapterDataObserver(mAdapterDataObserver);
        }
        RecyclerView.LayoutManager curLayoutManager = mRecyclerView.getLayoutManager();
        RecyclerView.LayoutManager layoutManager;
        if (curLayoutManager instanceof SafeLinearLayoutManager) {
            layoutManager = curLayoutManager;
            mRecyclerViewLoadMoreController = new RecyclerViewLoadMoreController(mContext, mAdapter, (LinearLayoutManager) layoutManager);
        } else if (curLayoutManager instanceof SafeStaggeredGridLayoutManager) {
            layoutManager = curLayoutManager;
            mRecyclerViewLoadMoreController = new RecyclerViewLoadMoreController(mContext, mAdapter, (SafeStaggeredGridLayoutManager) layoutManager);
        } else {
            layoutManager = new SafeLinearLayoutManager(mContext);
            ((SafeLinearLayoutManager) layoutManager).setOrientation(SafeLinearLayoutManager.VERTICAL);
            mRecyclerViewLoadMoreController = new RecyclerViewLoadMoreController(mContext, mAdapter, (LinearLayoutManager) layoutManager);
        }

        mRecyclerView.addOnScrollListener(mRecyclerViewLoadMoreController);
        mRecyclerViewLoadMoreController.setLoadMoreHandler(loadMoreContainer -> {
            CLog.d(TAG, "onLoadMore: %s", this);
            mListData.queryNextPage();
        });

        mRecyclerView.setHasFixedSize(true);
        mRecyclerView.setItemViewCacheSize(10);
        mRecyclerView.setDrawingCacheEnabled(true);

        mRecyclerView.setAdapter(mAdapter);
        mRecyclerView.setLayoutManager(layoutManager);

        if (mSwipeRefreshLayout != null) {
            mSwipeRefreshLayout.setOnRefreshListener(() -> {
                CLog.d(TAG, "onRefresh: %s", this);
                mListData.queryFirstPage();
            });
        }
    }

    public void onListEvent(EventWithRequestTag event) {
        CLog.d(TAG, "onListEvent: %s %s", this, event.requestTag.equals(mListData.getRequestTag()));
        if (!event.requestTag.equals(mListData.getRequestTag())) {
            return;
        }
        tryToStopLoading();
        if (event.isFailed()) {
            return;
        }
        mDataHasLoaded = true;
        if (mAdapter instanceof BaseDiffAdapter) {
            ((BaseDiffAdapter) mAdapter).update(mListData.getListPageInfo().dataList);
        } else {
            mAdapter.setList(mListData.getListPageInfo().dataList);
            mAdapter.notifyDataSetChanged();
        }
        mRecyclerViewLoadMoreController.loadMoreFinish(false, mListData.getListPageInfo().hasMore());
        updateEmptyStatus();
    }

    public void updateEmptyStatus() {
        if (mListData.getListPageInfo().isEmpty()) {
            if (mEmptyCallback != null) {
                mEmptyCallback.run();
            }
        } else {
            if (mNotEmptyCallback != null) {
                mNotEmptyCallback.run();
            }
        }
    }

    public void setEmptyCallback(Runnable emptyCallback) {
        mEmptyCallback = emptyCallback;
    }

    public void setNotEmptyCallback(Runnable notEmptyCallback) {
        mNotEmptyCallback = notEmptyCallback;
    }

    public void onDestroy() {
        if (mAdapter instanceof BaseDiffAdapter && mAdapterDataObserver != null) {
            mAdapter.unregisterAdapterDataObserver(mAdapterDataObserver);
        }
        mEmptyCallback = null;
    }
}
